package com.ivanceras.server.util;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;

import com.google.gwt.event.logical.shared.HasBeforeSelectionHandlers;
import com.ivanceras.shared.dao.DAO_Ad_column;
import com.ivanceras.shared.dao.DAO_Ad_field;
import com.ivanceras.shared.dao.DAO_Ad_tab;
import com.ivanceras.shared.dao.DAO_Ad_table;
import com.ivanceras.shared.dao.DAO_Ad_window;
import com.ivanceras.shared.db.EMF;
import com.ivanceras.shared.db.EntityManager;
import com.ivanceras.shared.db.Filter;
import com.ivanceras.shared.db.ModelDef;
import com.ivanceras.shared.db.ModelDef;
import com.ivanceras.shared.exception.DatabaseException;
import com.ivanceras.shared.exception.ModelDefinitionNotFoundException;
import com.ivanceras.shared.meta.ModelDefinitionProvider;
import com.ivanceras.shared.util.Configuration;

public class WindowBuilder {
	
	static BigDecimal windowId = new BigDecimal(0);
	
	
	public static void buildWindow(EntityManager em, String windowName, String[] tables) throws DatabaseException{
		windowId = windowId.add(new BigDecimal(1));
		DAO_Ad_window window = new DAO_Ad_window();
		window.setAd_window_id(windowId);
		window.setName(windowName);
		window.setCreated(new Date());
		window.setUpdated(new Date());
		window.setIsactive("Y");
		window.setEntitytype("M");
		em.insert(window);

		traverseChildren(em, tables[0], tables, windowId, new BigDecimal(0));
	}
	
	static HashMap<String, Boolean> hasBeenGenerated = new HashMap<String, Boolean>();
	
	static void traverseChildren(EntityManager em,String table, String[] includedTables, BigDecimal windowId, BigDecimal tabLevel) throws DatabaseException{
		try {
			ModelDef model = ModelDefinitionProvider.getDefinition(CStringUtils.capitalize(table.toLowerCase()));
			String tabName = CStringUtils.beautify(model.getModelName());
			DAO_Ad_table daoTable = DAO_Ad_table.cast(em.getOne(new DAO_Ad_table(), new Filter("tablename", Filter.EQUAL, table.toLowerCase())));
			int index = indexOf(includedTables, table);
			createTab(em, tabName, daoTable, windowId, tabLevel, index*10);
			hasBeenGenerated.put(table, true);
			System.out.println("Has been generated "+hasBeenGenerated);
			tabLevel = tabLevel.add(new BigDecimal(1));
			String[] children = model.getHasMany();
			if(children != null){
				for(String child : children){
					System.out.println("Processing: "+child);
					if(child.equals(table)){//one table tab for each window
						//self referenced, must be a tree;
					}else if(indexOf(includedTables, child) >= 0 && !hasBeenGenerated.containsKey(child)){
						traverseChildren(em, child, includedTables, windowId, tabLevel);
					}
				}
			}
		} catch (ModelDefinitionNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	static int indexOf(String[] tables, String table) {
		for(int i = 0; i < tables.length; i++){
			if(table.equals(tables[i])){
				return i;
			}
		}
		return -1;
	}

	static BigDecimal tabId = new BigDecimal(0);
	static BigDecimal fieldId = new BigDecimal(0);
	
	static void createTab(EntityManager em, String tabName, DAO_Ad_table table, BigDecimal windowId, BigDecimal tabLevel, int tabSeqNo) throws DatabaseException{
		
		DAO_Ad_tab tab = new DAO_Ad_tab();
		tabId = tabId.add(new BigDecimal(1));
		tab.setAd_tab_id(tabId);
		tab.setName(tabName);
		tab.setIssinglerow("Y");
		tab.setAd_table_id(table.getAd_table_id());
		tab.setCreated(new Date());
		tab.setUpdated(new Date());
		tab.setIsactive("Y");
		tab.setAd_window_id(windowId);
		tab.setSeqno(new BigDecimal(tabSeqNo));
		tab.setTablevel(tabLevel);
		tab.setEntitytype("M");
		em.insert(tab);

		DAO_Ad_column[] columns = DAO_Ad_column.cast(em.getChildren(table, new DAO_Ad_column()));
		for(DAO_Ad_column col : columns){
			DAO_Ad_field field = new DAO_Ad_field();
			fieldId = fieldId.add(new BigDecimal(1));
			field.setName(col.getName());
			field.setAd_field_id(fieldId);
			field.setAd_column_id(col.getAd_column_id());
			field.setCreated(new Date());
			field.setUpdated(new Date());
			field.setEntitytype("M");
			field.setIsactive("Y");
			field.setAd_tab_id(tabId);
			field.setSeqno(new BigDecimal(30));
			if(col.getIskey().equals("Y")){
				field.setSeqno(new BigDecimal(10));
			}
			if(col.getIsidentifier().equals("Y")){
				field.setSeqno(new BigDecimal(20));
			}
			if(isDisplayed(col)){
				field.setIsdisplayed("Y");
			}else{
				field.setIsdisplayed("N");
			}
			em.insert(field);
		}
		
	}
	
	static boolean isDisplayed(DAO_Ad_column column){
		String columnName = column.getColumnname().toLowerCase();
		String[] notDisplayedColumns = {"created", "createdby", "updated", "updatedby", "ad_org_id", "ad_client_id"};
		for(String ndc : notDisplayedColumns){
			if(ndc.equals(columnName)){
				return false;
			}
		}
		return true;
	}
	
	/**
	 * build a heirarchy list of table which defines the relationships of data
	 * @throws DatabaseException 
	 */
	static void buildDefinedWindows(EntityManager em) throws DatabaseException{
		String windowName1 = "Window Tab, & Field";
		String[] includedTables1 = {"ad_window", "ad_tab", "ad_table", "ad_field", "ad_column"};
		
		String windowName2 = "Table & Columns";
		String[] includedTables2 = {"ad_table","ad_column"};
		
		String windowName3 = "Elements";
		String[] includedTables3 = {"ad_element"};
	
		buildWindow(em, windowName1, includedTables1);
		buildWindow(em, windowName2, includedTables2);
		buildWindow(em, windowName3, includedTables3);
	}
	
	public static void main(String[] args){
		EntityManager em = null;
		try {
			em = EMF.get();
			em.beginTransaction();
			MetaTableExtractor.truncateAppDtables(em);
			MetaTableExtractor.extractToAppD(em, Configuration.dbUser, "%");
			buildDefinedWindows(em);
			em.commitTransaction();
		} catch (DatabaseException e) {
			try {
				em.rollbackTransaction();
			} catch (DatabaseException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}
	}

}
